home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
fst03f.zip
/
diskio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-09
|
32KB
|
1,081 lines
/* diskio.c -- Disk/sector I/O for fst
Copyright (c) 1995-1996 by Eberhard Mattes
This file is part of fst.
fst is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
fst is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with fst; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define INCL_DOSDEVIOCTL
#define INCL_DOSDEVICES
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <io.h>
#include <fcntl.h>
#include <limits.h>
#include "fst.h"
#include "crc.h"
#include "diskio.h"
/* Size of the hash table used for speeding up reading snapshot files. */
#define HASH_SIZE 997
/* This value marks the end of a hash chain. It should be an
`impossible' sector number. */
#define HASH_END 0xffffffff
/* Method for reading and writing sectors. */
enum disk_io_type
{
DIOT_DISK_DASD, /* DosRead, DosWrite */
DIOT_DISK_TRACK, /* Logical: DSK_READTRACK, DSK_WRITETRACK */
DIOT_SNAPSHOT, /* Snapshot file */
DIOT_CRC /* CRC file */
};
/* Data for DIOT_DISK_DASD. */
struct diskio_dasd
{
HFILE hf; /* File handle */
char sec_mode; /* TRUE iff sector mode active */
};
/* Data for DIOT_DISK_TRACK. */
struct diskio_track
{
HFILE hf; /* File handle */
ULONG layout_size; /* Size of structure pointed to by playout */
ULONG hidden; /* Hidden sectors */
ULONG spt; /* Sectors per track */
ULONG heads; /* Number of heads */
TRACKLAYOUT *playout; /* Parameter for DSK_READTRACK */
BYTE *track_buf; /* Buffer for one track */
};
/* Data for DIOT_SNAPSHOT. */
struct diskio_snapshot
{
HFILE hf; /* File handle */
ULONG sector_count; /* Total number of sectors */
ULONG *sector_map; /* Table containing relative sector numbers */
ULONG *hash_next; /* Hash chains */
ULONG version; /* Format version number */
ULONG hash_start[HASH_SIZE]; /* Hash chain heads */
};
/* Data for DIOT_CRC. */
struct diskio_crc
{
FILE *f; /* Stream */
ULONG version; /* Format version number */
crc_t *vec; /* See diskio_crc_load() */
};
/* DISKIO structure. */
struct diskio
{
enum disk_io_type type; /* Method */
ULONG spt; /* Sectors per track */
ULONG total_sectors; /* Total number of sectors */
union
{
struct diskio_dasd dasd;
struct diskio_track track;
struct diskio_snapshot snapshot;
struct diskio_crc crc;
} x; /* Method-specific data */
};
/* This variable selects the method of direct disk I/O to use.
ACCESS_DASD selects DosRead and DosWrite, ACCESS_LOG_TRACK selects
DSK_READTRACK and DSK_WRITETRACK for logical disks. */
enum access_type diskio_access;
/* Non-zero if write access is required. */
char write_enable;
/* Non-zero if removable disks are allowed. */
char removable_allowed;
/* Non-zero to ignore failure to lock the disk. */
char ignore_lock_error;
/* Non-zero to disable locking (FOR TESTING ONLY!). */
char dont_lock;
/* Type of the save file. */
enum save_type save_type;
/* This is the save file. */
FILE *save_file;
/* Name of the save file. There is no save file if this variable is
NULL. */
const char *save_fname;
/* Number of sectors written to the save file. */
ULONG save_sector_count;
/* Number of elements allocated for save_sector_map. */
ULONG save_sector_alloc;
/* This table maps logical sector numbers to relative sector numbers
in the snap shot file, under construction. */
ULONG *save_sector_map;
/* Return the drive letter of a file name, if any, as upper-case
letter. Return 0 if there is no drive letter. */
static char fname_drive (const char *s)
{
if (s[0] >= 'A' && s[0] <= 'Z' && s[1] == ':')
return s[0];
else if (s[0] >= 'a' && s[0] <= 'z' && s[1] == ':')
return (char)(s[0]-'a'+'A');
else
return 0;
}
/* Return the currently selected drive as upper-case letter. */
static char cur_drive (void)
{
ULONG drive, map;
if (DosQueryCurrentDisk (&drive, &map) != 0)
return 0;
return (char)(drive - 1 + 'A');
}
/* Obtain access to a disk, snapshot file, or CRC file. FNAME is the
name of the disk or file to open. FLAGS defines what types of
files are allowed; FLAGS is the inclusive OR of one or more of
DIO_DISK, DIO_SNAPSHOT, and DIO_CRC. Open for writing if FOR_WRITE
is non-zero. */
DISKIO *diskio_open (PCSZ fname, unsigned flags, int for_write)
{
ULONG rc, action, mode, parmlen, datalen, pos, nread, hash, i, ulParm, *map;
HFILE hf;
UCHAR data;
BIOSPARAMETERBLOCK bpb;
BYTE parm[2];
int h;
DISKIO *d;
/* Writing required the -w option. On the other hand, -w should not
be used unless writing is requested. */
if (!for_write && write_enable)
error ("Do not use the -w option for actions that don't write sectors");
if (for_write && !write_enable)
error ("Use the -w option for actions that write sectors");
/* Allocate a DISKIO structure. */
d = xmalloc (sizeof (*d));
/* Check for drive letter (direct disk access). */
if (isalpha ((unsigned char)fname[0]) && fname[1] == ':' && fname[2] == 0)
{
/* Direct disk access requested. Check if this is allowed. */
if (!(flags & DIO_DISK))
error ("A drive name cannot be used for this action");
/* Open a file handle for the logical disk drive. */
if (for_write)
mode = (OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR
| OPEN_FLAGS_RANDOM | OPEN_FLAGS_NOINHERIT
| OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE);
else
mode = (OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR
| OPEN_FLAGS_RANDOM | OPEN_FLAGS_NOINHERIT
| OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY);
rc = DosOpen (fname, &hf, &action, 0, FILE_NORMAL,
OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
mode, 0);
if (rc != 0)
error ("Cannot open %s (rc=%lu)", fname, rc);
if (!dont_lock)
{
/* Attempt to lock the drive. */
parm[0] = 0; parmlen = 1;
datalen = 1;
rc = DosDevIOCtl (hf, IOCTL_DISK, DSK_LOCKDRIVE,
parm, parmlen, &parmlen,
&data, datalen, &datalen);
if (rc != 0 && (for_write || !ignore_lock_error))
error ("Cannot lock drive");
if (rc != 0)
{
warning (0, "Cannot lock drive -- proceeding without locking");
warning_cont (" NOTE: Results are not reliable without locking!");
}
else
{
/* Issue DSK_REDETERMINEMEDIA to flush the buffers of
the file system driver. */
parm[0] = 0; parmlen = 1;
datalen = 1;
rc = DosDevIOCtl (hf, IOCTL_DISK, DSK_REDETERMINEMEDIA,
parm, parmlen, &parmlen,
&data, datalen, &datalen);
if (rc != 0)
warning (0, "Cannot flush the buffers of the file system "
"dri